package com.corpgovernment.common.utils;

import com.corpgovernment.common.deepmd5.Passwd;
import com.ctrip.framework.apollo.core.utils.StringUtils;
import org.apache.commons.codec.binary.Hex;

import java.security.MessageDigest;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

/**
 * @author majl
 * @date 2019-5-24
 */
public class Md5Util {
    //16进制
    public static final char[] HEX_ARRAY = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

    /**
     * 盐的位置
     */
    private static final Set<Integer> SALT_INDEX_SET = new HashSet<Integer>() {{
        int[] indexs = new int[]{0, 4, 6, 7, 9, 11, 17, 18, 22, 29, 32, 35, 40, 42, 45, 47};
        for (int i = 0; i < indexs.length; i++) {
            add(indexs[i]);
        }
    }};

    /**
     * 密码做md5并加入随机盐
     *
     * @param pwd
     * @return
     */
    public static String encodeMd5WithRandomSalt(String pwd) {
        String salt = genRandomStr();
        char[] result = new char[48];
        char[] pwdMd5 = md5Hex(pwd + salt).toCharArray();
        char[] saltArray = salt.toCharArray();
        for (int i = 0, pwdIndex = 0, saltIndex = 0; i < 48; i++) {
            if (SALT_INDEX_SET.contains(i)) {
                result[i] = saltArray[saltIndex++];
            } else {
                result[i] = pwdMd5[pwdIndex++];
            }
        }
        return new String(result);
    }

    /**
     * 生成16位随机的16进制字符串
     *
     * @return
     */
    public static String genRandomStr() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 16; i++) {
            sb.append(HEX_ARRAY[new Random().nextInt(16)]);
        }
        return sb.toString();
    }

    /**
     * 校验密码是否正确
     */
    public static boolean verifyMd5WithRandomSalt(String pwd, String md5) {
        if (pwd == null || "".equals(pwd)) {
            return false;
        }
        if (md5 == null || md5.length() != 48) {
            return false;
        }
        char[] pwdMd5 = new char[32];
        char[] saltArray = new char[16];
        char[] resultArray = md5.toCharArray();
        for (int i = 0, pwdIndex = 0, saltIndex = 0; i < 48; i++) {
            if (SALT_INDEX_SET.contains(i)) {
                saltArray[saltIndex++] = resultArray[i];
            } else {
                pwdMd5[pwdIndex++] = resultArray[i];
            }
        }
        String salt = new String(saltArray);
        return md5Hex(pwd + salt).equals(new String(pwdMd5));
    }

    /**
     * 获取十六进制字符串形式的MD5摘要
     */
    public static String md5Hex(String src) {
        try {
            MessageDigest md5 = MessageDigest.getInstance("MD5");
            byte[] bs = md5.digest(src.getBytes());
            return new String(new Hex().encode(bs));
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String getDeepMd5Msg(String account, String pwd) {
        String md5OfPwd = new Passwd().deepMD5(pwd);
        return new Passwd().deepMD5(account + md5OfPwd);
    }

    public static boolean verifyDeepMd5Msg(String account, String pwd, String md5) {
        if (StringUtils.isBlank(md5)) {
            return false;
        }
        if (md5.equals(pwd)) {
            return true;
        }
        return md5.equals(getDeepMd5Msg(account, pwd));
    }
}
